package org.example.mall.admin.controller.manage;


import cn.hutool.core.io.IoUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.example.mall.admin.configuration.resource.Inner;
import org.example.mall.admin.model.entity.manage.SysFile;
import org.example.mall.admin.service.manage.SysFileService;
import org.example.mall.admin.util.BusOp;
import org.example.mall.admin.util.PermissionUtil;
import org.example.mall.admin.util.R;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * <p>
 * 文件管理表 前端控制器
 * </p>
 *
 * @author hzq
 * @since 2022-01-04
 */
@Api(tags = "文件管理表")
@RestController
@AllArgsConstructor
@RequestMapping("/manage/sysFile")
public class SysFileController {

    private final SysFileService sysFileService;

    /**
     * 分页查询
     *
     * @param page    分页对象
     * @param sysFile 文件管理
     */
    @GetMapping("/page")
    @ApiOperation(value = "分页查询", notes = "分页查询")
    public R<IPage<SysFile>> getSysFilePage(Page page, SysFile sysFile) {
        return R.ofSuccess(sysFileService.getPage(page, sysFile));
    }

    /**
     * 通过id删除文件管理
     *
     * @param id 文件id
     */
    @DeleteMapping("/{id}")
    @PreAuthorize("hasAuthority('material_manage')")
    @ApiOperation(value = "通过id删除文件管理", notes = "通过id删除文件管理")
    public R<Boolean> removeById(@ApiParam(name = "id", value = "文件id") @PathVariable Long id) {
        return R.ofSuccess("删除文件成功",
                BusOp.mustSucceed(sysFileService.deleteFile(id), "删除文件失败"));
    }

    @ApiOperation("移动素材")
    @PutMapping("/moveMaterialFile")
    @PreAuthorize("hasAuthority('material_manage')")
    public R<Boolean> moveMaterialFile(@ApiParam(name = "treeId", value = "分类id") @RequestParam Integer treeId,
                                       @ApiParam(name = "fileIds", value = "素材id英文逗号分割字符串") @RequestParam String fileIds) {
        return R.ofSuccess("移动素材成功", sysFileService.moveMaterialFile(treeId, fileIds));
    }

    /**
     * 上传文件 文件名采用md5Hex,避免原始文件名中带"-"符号导致下载的时候解析出现异常
     *
     * @param bucketName 桶名称
     * @param file       资源
     * @param treeId     分类id
     * @return R(/ bucketName / fileName / url)
     */
    @ApiOperation("上传文件")
    @PostMapping(value = "/upload")
    public R<Map<String, String>> upload(@RequestParam(required = false, defaultValue = "TMP") String bucketName,
                                         @RequestPart("file") MultipartFile file,
                                         @RequestParam(name = "treeId", required = false) Integer treeId) {
        PermissionUtil.checkFileMaterial(treeId);
        return sysFileService.uploadFile(bucketName, file, treeId);
    }

    /**
     * 上传网络文件
     *
     * @param bucketName 桶名称
     * @param netUrl     网络文件地址
     * @return R(/ bucketName / fileName / url)
     */
    @ApiOperation("上传网络文件")
    @PostMapping(value = "/uploadNet")
    public R<Object> uploadNet(@ApiParam(name = "bucketName", value = "桶名称") @RequestParam(required = false, defaultValue = "TMP") String bucketName,
                               @ApiParam(name = "netUrl", value = "网络文件地址") @RequestParam String netUrl,
                               @ApiParam(name = "fileName", value = "附件名称") @RequestParam(required = false) String fileName) {
        return R.ofSuccess("上传网络附件成功",
                BusOp.mustNotNull(sysFileService.uploadNetFile(bucketName, netUrl, fileName), "上传网络附件失败"));
    }

    /**
     * 获取文件
     *
     * @param bucket   桶名称
     * @param fileName 文件空间/名称
     * @return 文件流
     */
    @GetMapping
    @Inner(false)
    @ApiOperation("获取文件")
    public void file(@ApiParam(name = "bucket", value = "桶名称") @RequestParam String bucket,
                     @ApiParam(name = "fileName", value = "文件空间/名称") @RequestParam String fileName,
                     HttpServletResponse response) {
        sysFileService.getFile(bucket, fileName, response);
    }

    /**
     * 获取本地（resources）文件
     *
     * @param fileName 文件名称
     * @param response 文件流
     */
    @SneakyThrows
    @ApiOperation("获取本地（resources）文件")
    @GetMapping("/localFile")
    public void localFile(@ApiParam(name = "fileName", value = "文件路径") @RequestParam String fileName,
                          HttpServletResponse response) {
        ClassPathResource resource = new ClassPathResource("file/" + fileName);
        response.setContentType("application/octet-stream; charset=UTF-8");
        IoUtil.copy(resource.getInputStream(), response.getOutputStream());
    }

}

